﻿#include "CELLServer.h"

#include "CELL.h"
#include "CELLClient.h"
#include "CELLTimestamp.hpp"
#include <thread>
#include <mutex>
#include <vector>
#include <map>
#include <memory>
#include "INetEvent.h"
#include <iostream>
#include <string.h>


CELLServer::CELLServer() 
{
	
}

CELLServer::~CELLServer()
{
	CELLLog_Info("CELLServer %d Close ===== begin", _id);
	Close();
	CELLLog_Info("CELLServer %d Close ===== end", _id);
}

// 设置id
void CELLServer::SetId(int id)
{
	_id = id;
	// _taskServer.serverId = id;
}

void CELLServer::SetEventObj(INetEvent* event)
{
	_pNetEvent = event;
}

// 处理网络消息
void CELLServer::CELLServer::OnRun(CELLThread* pthread)
{
	while (pthread->isRun())
	{
		if (!_clientsBuff.empty())
		{
			// 这里的锁是保证接受新链接线程和接受消息服务线程安全
			std::lock_guard<std::mutex> lock(_mutex);
			for (auto pClient : _clientsBuff)
			{
				// 将客户端缓冲队列中的客户端添加到正式客户端队列中
				_clients[pClient->sockfd()] = pClient;
				pClient->id = _id;
				if (_pNetEvent)
					_pNetEvent->OnNetJoin(pClient);
				OnClientJoin(pClient);
			}
			_clientsBuff.clear();
			_clients_change = true;
		}

		if (_clients.empty())
		{
			CELLThread::Sleep(1);
			// 如果没有客户端，也要更新旧的时间戳
			_old_time = CELLTime::getNowInMilliSec();
			continue;
		}

		// 心跳检测
		CheckTime();

		if (!DoNetEvents())
		{
			// select错误
			pthread->Exit();
			break;
		}

		DoMsg();
	}
	CELLLog_Info("CELLServer %d OnRun exit", _id);
	return;
}

// 
void CELLServer::DoMsg()
{
	CELLClient* pClient = nullptr;
	for (auto itr : _clients)
	{
		pClient = itr.second;
		while (pClient->hasMsg())
		{
			// 处理最前面的消息
			OnNetMsg(pClient, pClient->front_msg());
			// 移除这条消息(删除接收缓冲区最前的一条消息)
			pClient->pop_front_msg();
		}
	}
}

// 客户端离开
void CELLServer::OnClientLeave(CELLClient* pClient)
{
	if (_pNetEvent)
		_pNetEvent->OnNetLeave(pClient);
	_clients_change = true;
	delete pClient;
}

// 新客户端加入
void CELLServer::OnClientJoin(CELLClient* pClient)
{
	
}

// 检测本类中所有正式客户端队列的心跳
void CELLServer::CheckTime()
{
	auto tNow = CELLTime::getNowInMilliSec();
	// 得到每次检测所有客户端心跳时的时间戳
	auto dt = tNow - _old_time;
	// 更新上一次时间戳
	_old_time = tNow;
	CELLClient* pClient = nullptr;
	// 在循环中不改变迭代器指针，在循环中会删除元素，在这之间进行改变
	for (auto iter = _clients.begin(); iter != _clients.end(); )
	{
		pClient = iter->second;
		// 心跳检测
		if (pClient->checkHeart(dt))
		{
#ifdef CELL_USE_IOCP
			// 使用IOCP模式下面，当客户端被心跳检测移除时，客户端暂时不能被释放(OnCLientLeave)
				// 因为 提交了接收数据或发送数据的任务 关闭套接字后IOCP会知晓并反应,
				// (反应会使用到client的IO_DATA_BASE)
			if (pClient->isPostIoAction())
				pClient->destory(); // 先关闭socket就可以，删除client交给IOCP
			else
				// 没有提交接收或者发送任务关闭sockfdIOCP不会收到通知
				OnClientLeave(pClient);
#else
			// select或epoll模式下：客户端已死亡, 触发客户端离开事件, 移除本客户端
			OnClientLeave(pClient);
#endif // #ifdef CELL_USE_IOCP
			
			// 在这里进行迭代器指针的自增(后置++，先赋值再自增)
			auto iterOld = iter++;
			_clients.erase(iterOld);
			continue;
		}
		// 定时发送数据检测
		// iter->second->checkSend(dt);
		// 在这里进行迭代器指针的自增
		++iter;
	}
}

// 接收数据 处理粘包 拆包
int CELLServer::RecvData(CELLClient* pClient)
{
	// 接受客户端数据
	int nlen = pClient->RecvData();
	if (nlen <= 0)
	{
		return SOCKET_ERROR;
	}
	// 触发<接收到网络事件>事件
	if (_pNetEvent)
		_pNetEvent->OnNetRecv(pClient);
	return nlen;
}

// 处理消息，响应网络消息
void CELLServer::OnNetMsg(CELLClient* pCLient, DataHeader* header)
{
	if (_pNetEvent)
		_pNetEvent->OnNetMsg(this, pCLient, header);
}

// 接收消息(这个方法是用于IOCP的接收计数: IOCP完成接收数据的任务调用)
void CELLServer::OnNetRecv(CELLClient* pClient)
{
	if (_pNetEvent)
		_pNetEvent->OnNetRecv(pClient);
}

// 关闭socket
void CELLServer::Close()
{
	// _taskServer.Close();
	_thread.Close();
}

// 操作客户端缓冲队列
void CELLServer::AddClient(CELLClient* pClient)
{
	// 这里的锁是保证接受新链接线程和接受消息服务线程安全
	std::lock_guard<std::mutex> lock(_mutex);
	_clientsBuff.push_back(pClient);
}

void CELLServer::Start()
{
	// 启动任务服务线程，用于添加耗io操作的任务
	// _taskServer.Start();
	_thread.Start(
		// onCreate
		nullptr, 
		// onRun
		[this](CELLThread* pthread) {
			OnRun(pthread);
		},
		// onDestory
		[this](CELLThread* pthread) {
			ClearClients();
		}
	);
}

// 获取客户端队列长度
size_t CELLServer::GetClientCount()
{
	return _clientsBuff.size() + _clients.size();
}

// 释放正式客户端和缓冲客户端队列空间
void CELLServer::ClearClients()
{
	for (auto iter : _clients)
	{
		delete iter.second;
	}
	_clients.clear();

	for (auto iter : _clientsBuff)
	{
		delete iter;
	}
	_clientsBuff.clear();
}

// 添加发送消息服务
void CELLServer::AddSendTask(CELLClient* pClient, DataHeader* header)
{
	// 任务加入一个匿名函数
	/*_taskServer.AddTask([pClient, header]() {
		pClient->SendData(header);
	});*/
}

// 注册时间事件，单位(秒)
unsigned int CELLServer::
add_time_event(CELLTimer::time_callback cb, void *ctx, unsigned int after_sec, int repeat)
{
	return _time_event.register_time_event(cb, ctx, after_sec, repeat);
}

// 更新时间事件，单位(秒)
void CELLServer::
mod_time_event(unsigned int timerid, unsigned int after_sec, int repeat)
{
	_time_event.update_time_event(timerid, after_sec, repeat);
}

// 删除时间事件，单位(秒)
void CELLServer::
del_time_event(unsigned int timerid)
{
	_time_event.unregister_time_event(timerid);
}
